package ControllerLayer.ControlServices.Normalizer;

import DataLayer.ImageDataContainer.ImageComponentsInfo.IImageComponentsInfo;
import DataLayer.ImageDataContainer.ImageComponentsInfo.SingleCharImageInfo;
import DataLayer.ImageDataContainer.ImageInfo.IImageInfo;
import DataLayer.KnowledgeBase.IKnowledgeBaseControl;
import DataLayer.KnowledgeBase.SerializableBufferedImage;
import java.awt.AlphaComposite;
import java.awt.image.BufferedImage;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.awt.Graphics2D;
import java.awt.RenderingHints;


public class MainNormalizer implements INormalizer {

    private static final int IMG_WIDTH = 20;
    private static final int IMG_HEIGHT = 20;
    private static int numPixPerRC = 16;
    private static int[] hist;


    public MainNormalizer() {
        // TODO add implementation
    }

    public void normalizeCharacters(IImageComponentsInfo imageComponentsInfo, IImageInfo imageInfo, IKnowledgeBaseControl knowledgeBaseControl) {
        //retreive all the character coordinates from the imageComponentsInfo, and the preprocessed image
        ////System.out.println("normalizeCharacters");
        ArrayList<SingleCharImageInfo> charList = new ArrayList<SingleCharImageInfo>();
        charList = imageComponentsInfo.getAllCharImageInfo();
        BufferedImage preprocImg = imageInfo.getPreprocessedImage();

        //for every character get the subimage
        for (SingleCharImageInfo sCh : charList)
        {
            ////System.out.println(sCh.ch);
            if ( ! ((sCh.ch.equals("_")) || (sCh.ch.equals("*")))) {
                try {
                    ////System.out.println("MainNormalizer: coord: " + sCh.x1 + " " + sCh.y1 + " " + sCh.x2 + " " + sCh.y2 + " letter: " + sCh.ch);
                    BufferedImage singleChar = preprocImg.getSubimage(sCh.y1, sCh.x1, sCh.y2 - sCh.y1 + 1, sCh.x2 - sCh.x1 + 1);
                    //send it for normalization
                    //BufferedImage normChar = normalizeSingleChar(singleChar);

                    SerializableBufferedImage seriNorm = new SerializableBufferedImage(singleChar);
                    //add it to the database
                    knowledgeBaseControl.getKnowledgeBase().addNewImage(seriNorm, sCh.ch, this);
                } catch (NoSuchAlgorithmException ex) {
                    System.out.println(ex);
                }
            }
        }
    }

    /**
     *
     * @param originalImg this image will be normalized
     * @return normalized image (20x20 pixels, cutout letter)
     */
    public BufferedImage normalizeSingleChar(BufferedImage originalImg) {
        // TODO add implementation
        int width = originalImg.getWidth();
        int height = originalImg.getHeight();
        //System.out.println("MainNormalizer: received image width = " + width + " height = " + height);
        numPixPerRC = (int)((width + height)/2 * 5 / 100);
        int i = 0;
        int j = 0;
        int x = 0;  //x coordinate of image right angle
        int y = 0;  //y coordinate of image right angle
        int w;  //new width
        int h;  //new hight
        int numPix = 0; //Number of pixels from row/column
        int y1 = 0;
        hist = new int[height];
        boolean first = true;
        int maxY = 0;
        int maxHeight = 0;
        int sum = 0;

        for(i = 0; i < height; i++){  //make histogram
                for(j = 0; j < width; j++){
                    if (originalImg.getRGB(j, i) != -1){
                        hist[i]++; //number of non white pixels in each row
                    }
                }
        }

        for(i = 0; i < height; i++){  //getting the largest object y coordinate and height
            if (hist[i] > numPixPerRC){
                sum++;
                if (first){
                    y1 = i;
                    first = false;
                }
                if (i == (height - 1)&&(!first)){ //last row
                    if(sum > maxHeight){
                        maxHeight = sum;
                        maxY = y1;
                    }
                }
             }else{
                if(sum > maxHeight){
                    maxHeight = sum;
                    maxY = y1;
                }
                sum = 0;
                first = true;
             }
        }
        y = maxY;
        h = maxHeight;

        //Getting the left x coordinate of the letter
        i = 0;
        j = 0;
        numPix = 0;
        while ((j < width) && (numPix < numPixPerRC)) {
            if (originalImg.getRGB(j, i) != -1){
                numPix++;
            }
            i++;
            if (i == height) {
                j++;
                i = 0;
                numPix = 0;
            }
        }
        x = j;
        
        //Getting the right x coordinate of the letter
        i = 0;
        j = width - 1;
        numPix = 0;
        while ((j > 0) && (numPix < numPixPerRC)) {
            if (originalImg.getRGB(j, i) != -1){
                numPix++;
            }
            i++;
            if (i == height) {
                j--;
                i = 0;
                numPix = 0;
            }
        }
        //Setting the image width
        w = j - x + 1;

        try{
        BufferedImage normalizedImage = originalImg.getSubimage(x, y, w, h);
        //normalizing the character
        BufferedImage resizedImg = resizeImage(normalizedImage);
        //converting to normalized size
        return resizedImg;
        }catch (Exception ex)
        {
            ////System.out.println("MainNormalizer: " + x + " " + y + " " + w + " " + h + " " + ex);
        }
        return null;
    }

    /**
     *
     * @param originalImage this image will be resized
     * @return resized image
     */
    public static BufferedImage resizeImage(BufferedImage originalImage) {

        BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, 10);
        Graphics2D g = resizedImage.createGraphics();
        g.setComposite(AlphaComposite.Src);
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null);
        g.dispose();

        return resizedImage;
    }
}
